package util

import (
	"bytes"
	"encoding/json"
	"fmt"
	"gitee.com/manoshi/go-util/exception"
	"github.com/gin-gonic/gin"
	"io"
	"io/ioutil"
	"net/http"
	"net/url"
	"strconv"
	"strings"
)

func ParamInt64(c *gin.Context, key string) int64 {
	return int64(ParamInt(c, key))
}
func ParamInt32NoNeed(c *gin.Context, key string) int32 {
	return int32(ParamIntNoNeed(c, key))
}
func ParamInt32(c *gin.Context, key string) int32 {
	return int32(ParamInt(c, key))
}

func ParamInt16(c *gin.Context, key string) int16 {
	return int16(ParamInt(c, key))
}

func ParamInt8(c *gin.Context, key string) int8 {
	return int8(ParamInt(c, key))
}

func ParamUint64(c *gin.Context, key string) uint64 {
	return uint64(ParamInt(c, key))
}

func ParamUint32(c *gin.Context, key string) uint32 {
	return uint32(ParamInt(c, key))
}

func ParamUint16(c *gin.Context, key string) uint16 {
	return uint16(ParamInt(c, key))
}
func ParamUint8NoNeed(c *gin.Context, key string) uint8 {
	return uint8(ParamIntNoNeed(c, key))
}
func ParamUint8(c *gin.Context, key string) uint8 {
	return uint8(ParamInt(c, key))
}

func ParamIntNoNeed(c *gin.Context, key string) int {
	v := ParamNoNeed(c, key)
	if v == "" {
		return 0
	}
	i, err := strconv.Atoi(v)
	if err != nil {
		exception.ThrowsErrS("PARAMS_ERR", "请传入正确的数字")
	}
	return i
}
func ParamInt(c *gin.Context, key string) int {
	v := Param(c, key)
	i, err := strconv.Atoi(v)
	if err != nil {
		exception.ThrowsErrS("PARAMS_ERR", "请传入正确的数字")
	}
	return i
}

func ParamNoNeed(c *gin.Context, key string) string {
	v, ok := c.GetQuery(key)
	if !ok {
		return ""
	}
	return v
}

func Param(c *gin.Context, key string) string {
	v, ok := c.GetQuery(key)
	if !ok {
		exception.ThrowsErrS("PARAMS_ERR", fmt.Sprintf("%s不能为空", key))
	}
	return v
}

const (
	ApplicationJSON = "application/json"
	XmlForm         = "application/x-www-form-urlencoded;charset=utf-8"
)

func Get(client http.Client, apiUrl string, params url.Values) ([]byte, error) {
	url := fmt.Sprintf("%s?%s", apiUrl, params.Encode())
	rep, err := client.Get(url)
	if err != nil {
		return nil, err
	}
	defer rep.Body.Close()
	data, err := io.ReadAll(rep.Body)
	if err != nil {
		return nil, err
	}
	return data, nil
}

func GetHeader(client http.Client, apiUrl string, params url.Values, header map[string]string) ([]byte, error) {
	url := fmt.Sprintf("%s?%s", apiUrl, params.Encode())
	request, err := http.NewRequest(http.MethodGet, url, nil)
	if err != nil {
		return nil, err
	}
	if header != nil {
		for k, v := range header {
			request.Header.Add(k, v)
		}
	}
	response, err := client.Do(request)
	if err != nil {
		return nil, err
	}
	defer response.Body.Close()
	data, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return nil, err
	}
	return data, nil
}

func PostFormStr(client http.Client, url string, params string, header map[string]string) ([]byte, error) {
	p := StrToUrlValue(params)
	requestStr := p.Encode()
	buf := strings.NewReader(requestStr)
	request, err := http.NewRequest(http.MethodPost, url, buf)
	if err != nil {
		return nil, err
	}
	request.Header.Add("Content-Type", XmlForm)
	if header != nil {
		for k, v := range header {
			request.Header.Add(k, v)
		}
	}

	response, err := client.Do(request)
	if err != nil {
		return nil, err
	}
	defer response.Body.Close()
	data, err := io.ReadAll(response.Body)
	if err != nil {
		return nil, err
	}

	return data, err
}

func PostJSONStr(client http.Client, url string, params string, header map[string]string) ([]byte, error) {
	request, err := http.NewRequest(http.MethodPost, url, bytes.NewBufferString(params))
	if err != nil {
		return nil, err
	}
	request.Header.Add("Content-Type", ApplicationJSON)
	if header != nil {
		for k, v := range header {
			request.Header.Add(k, v)
		}
	}

	response, err := client.Do(request)
	if err != nil {
		return nil, err
	}
	defer response.Body.Close()
	data, err := io.ReadAll(response.Body)
	if err != nil {
		return nil, err
	}

	return data, err
}

func PostJson(client http.Client, url string, params interface{}) ([]byte, error) {
	return PostJsonHeader(client, url, params, nil)
}

func PostJsonHeader(client http.Client, url string, params interface{}, header map[string]string) ([]byte, error) {
	buf := bytes.NewBuffer(nil)
	encoder := json.NewEncoder(buf)
	if err := encoder.Encode(params); err != nil {
		return nil, err
	}

	request, err := http.NewRequest(http.MethodPost, url, buf)
	if err != nil {
		return nil, err
	}

	request.Header.Add("Content-Type", "application/json")
	if header != nil {
		for k, v := range header {
			request.Header.Add(k, v)
		}
	}

	response, err := client.Do(request)
	if err != nil {
		return nil, err
	}
	defer response.Body.Close()
	data, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return nil, err
	}
	return data, nil
}

func PutJson(client http.Client, url string, params interface{}) ([]byte, error) {
	return PutJsonHeader(client, url, params, nil)
}

func PutJsonHeader(client http.Client, url string, params interface{}, header map[string]string) ([]byte, error) {
	buf := bytes.NewBuffer(nil)
	encoder := json.NewEncoder(buf)
	if err := encoder.Encode(params); err != nil {
		return nil, err
	}

	request, err := http.NewRequest(http.MethodPut, url, buf)
	if err != nil {
		return nil, err
	}

	request.Header.Add("Content-Type", "application/json")
	if header != nil {
		for k, v := range header {
			request.Header.Add(k, v)
		}
	}

	response, err := client.Do(request)
	if err != nil {
		return nil, err
	}
	defer response.Body.Close()
	data, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return nil, err
	}
	return data, nil
}
